package com.jltx.xq.zeus.startup

import android.content.Context
import android.os.Looper
import android.util.Log
import com.jltx.xq.zeus.startup.dispatcher.StartupManagerDispatcher
import com.jltx.xq.zeus.startup.execption.StartupException
import com.jltx.xq.zeus.startup.model.StartupSortStore
import com.jltx.xq.zeus.startup.sort.TopologySort
import com.jltx.xq.zeus.startup.utils.StartupLogUtils
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger

/**
 * @author aidenquan
 *         Created by junlintianxia on 2022/07/14.
 */
class StartupManager private constructor(
    private val context: Context,
    private val startupList: List<Startup<*>>?,
    private val needAwaitCount: AtomicInteger,
    private val completeListener: StartupListener?
) {
    private var awaitCountDownLatch: CountDownLatch? = null


    fun start(): StartupManager = apply {
        if (Looper.getMainLooper() != Looper.myLooper()) {
            throw StartupException("start method must be call in MainThread.")
        }

        if (awaitCountDownLatch != null) {
            throw StartupException("start method repeated call.")
        }

        if (startupList.isNullOrEmpty()) {
            StartupLogUtils.e { "startupList is empty in the current process." }
            return@apply
        }

        awaitCountDownLatch = CountDownLatch(needAwaitCount.get())

        TopologySort.sort(startupList).let {
            mDefaultManagerDispatcher.prepare()
            execute(it)
        }


    }

    private fun execute(sortStore: StartupSortStore) {
        sortStore.result.forEach { mDefaultManagerDispatcher.dispatch(it, sortStore) }
    }

    /**
     * Startup dispatcher
     */
    private val mDefaultManagerDispatcher by lazy {
        StartupManagerDispatcher(
            context,
            needAwaitCount,
            awaitCountDownLatch,
            startupList?.size ?: 0,
            completeListener
        )
    }

    /**
     * 去等待启动任务完成，这里面会卡主线程
     */
    fun await() {
        val count = needAwaitCount.get()
        try {
            awaitCountDownLatch?.await()
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
        StartupLogUtils.d { "await $count" }
        Log.d("GGGGG", "主线程任务完成")
    }


    class Builder {
        private var mStartupList = mutableListOf<AndroidStartup<*>>()
        private var mNeedAwaitCount = AtomicInteger()
        private var completeListener: StartupListener? = null

        fun addStartup(startup: AndroidStartup<*>) = apply {
            mStartupList.add(startup)
        }

        fun addAllStartup(list: List<AndroidStartup<*>>) = apply {
            list.forEach {
                addStartup(it)
            }
        }

        fun setListener(listener: StartupListener) = apply {
            completeListener = listener
        }

        fun build(context: Context): StartupManager {
            //记录有多少个在子线程执行，又需要主线程等待的任务
            mStartupList.forEach {
                //记录有多少个在子线程执行，并且又需要主线程等待的任务
                if (it.waitOnMainThread() && !it.callCreateOnMainThread()) {
                    mNeedAwaitCount.incrementAndGet()
                }
            }

            return StartupManager(
                context,
                mStartupList,
                mNeedAwaitCount,
                completeListener
            )
        }
    }
}
